package com.youi.security;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.youi.util.JedisUtils;
import com.youi.util.LogUtil;
import com.youi.util.SmsUtil;

/**
 * 请求管理
 * @author Administrator
 *
 */
public class RequestManage {
	
	public static Map<String, Long> ipBlackList=new HashMap<String, Long>();//ip黑名单  key=ip  value=加入黑名单的时间戳
	public static Map<String, Long> reqUrlList=new HashMap<String, Long>();//请求接口黑名单   key=url  value=加入黑名单的时间戳
	
	private static String REQUESTQUEUES="requestQueues";
	
	private static String MANAGERPhone="18520040243";
	
	public static boolean MSGSTATE=true;
	
	/**
	 * 安全认证
	 * @param url
	 * @param ip
	 * @return
	 */
	public static boolean safetyCertification(String url,String ip){
		if (url!=null&&ip!=null) {
			/**检查ip是否存在黑名单*/
			if (checkIpBlackList(ip)) {
				return true;
			}
			/**检查url是否在黑名单里*/
			if (checkUrlBlackList(url)) {
				return true;
			}
			return checkSafety(url, ip);
		}else {
			return true;
		}
	}
	
	/**
	 * 检查安全性  是否存在恶意请求
	 * @param url
	 * @param ip
	 * @return
	 */
	private static boolean checkSafety(String url,String ip){
		try {
			/**总的请求队列*/
			List<RequestQueue> requestQueues=null;
			if (JedisUtils.exists(REQUESTQUEUES)) {
				requestQueues=JedisUtils.getObjectList(REQUESTQUEUES, Request.class);
			}
			if (requestQueues==null) {
				requestQueues=new ArrayList<RequestQueue>();
			}		
			/**url请求队列*/
			List<Request> requests=null;
			if (JedisUtils.exists(url)) {
				requests=JedisUtils.getObjectList(url, Request.class);
			}
			if (requests==null) {
				requests=new ArrayList<Request>();
			}
			Date nowDate=new Date();
			/**url请求队列大于100 进行抽样检查*/
			if (requests.size()>=100) {
				Request firstRequest=requests.get(0);
				if ((nowDate.getTime()-firstRequest.getTimestamp())<=1000) { //一秒钟内同一个接口的请求量超过100
					/**抽样检查*/
					if(samplingRequestQueue(url, requestQueues)){
						/**存在恶意攻击  ip加入黑名单*/
						for (Request request : requests) {
							if (!ipBlackList.containsKey(ip)) {
								ipBlackList.put(request.getIp(), new Date().getTime());
							}
						}
						/**当ip黑名单达2W 则将接口关闭*/
						if (ipBlackList.size()>20000) {
							if (!reqUrlList.containsKey(url)) {
								reqUrlList.put(url, new Date().getTime());
							}
						}
						/**短信通知管理员*/
						if (MSGSTATE) {
							SmsUtil.cloundSendMessage("【王师傅特色美食】系统正在受到恶意攻击,请及时处理。", MANAGERPhone);
							MSGSTATE=false;
						}
						return true;
					}
				}
				/**清空*/
				requests=new ArrayList<Request>();
			}
			/**加入队列*/
			requests.add(new Request(ip,nowDate.getTime()));
			requestQueues.add(new RequestQueue(url, ip));
			/**请求总队列 大于1万时  删除前9千*/
			if (requestQueues.size()>=10000) {
				List<RequestQueue> requestQueuesNew=new ArrayList<RequestQueue>();
				for (int i = 9000; i < requestQueues.size(); i++) {
					requestQueuesNew.add(requestQueues.get(i));
				}
				JedisUtils.setObjectList(REQUESTQUEUES, requestQueuesNew, 1800);
			}else {
				JedisUtils.setObjectList(REQUESTQUEUES, requestQueues, 1800);
			}
			JedisUtils.setObjectList(url, requests, 1800);
		} catch (Exception e) {
			// TODO: handle exception
			LogUtil.Info("检查安全--是否存在恶意请求时异常["+e.toString()+"]");
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * 队列抽样  查询最近1000次的请求  当请求的达百分之90时 说明存在恶意攻击 （最近1000次请求里有900条是同一个请求）
	 * @param url
	 * @param requestQueues
	 * @return
	 */
	private static boolean samplingRequestQueue(String url,List<RequestQueue> requestQueues){
		int index=0;
		int y=0;
		RequestQueue requestQueue=null;
		for (int i = requestQueues.size()-1; i>0&&index<1000; i--,index++) {
			requestQueue=requestQueues.get(i);
			if (requestQueue.getUrl().equals(url)) {
				y++;
			}
		}
		if ((y/(float)index)>=0.9F) {
			return true;
		}
		return false;
	}
	
	
	/**
	 * 检查ip是否存在黑名单
	 * @param ip
	 * @return
	 */
	public  static  boolean checkIp(String ip){
		if (ipBlackList!=null&&ipBlackList.size()>0) {
			if (ipBlackList.containsKey(ip)) {
				return true;
			}
		}
		return false;
	}
	
	
	/**
	 * 检查ip是否存在黑名单  如果已存在24小时则解放
	 * @param ip
	 * @return
	 */
	public  static  boolean checkIpBlackList(String ip){
		if (ipBlackList!=null&&ipBlackList.size()>0) {
			if (ipBlackList.containsKey(ip)) {
				Long nowTime=new Date().getTime();
				Long blackTime=ipBlackList.get(ip);
				if (blackTime!=null&&nowTime-blackTime>1000*60*60*24) {//24小时后解除
					ipBlackList.remove(ip);
					return false;
				}
				return true;
			}
		}
		return false;
	}

	/**
	 * 检查url是否在黑名单里  
	 * @param url
	 * @return
	 */
	public  static  boolean checkUrl(String url){
		if (reqUrlList!=null&&reqUrlList.size()>0) {
			if (reqUrlList.containsKey(url)) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 检查url是否在黑名单里  如果已存在24小时则解放
	 * @param url
	 * @return
	 */
	public  static  boolean checkUrlBlackList(String url){
		if (reqUrlList!=null&&reqUrlList.size()>0) {
			if (reqUrlList.containsKey(url)) {
				Long nowTime=new Date().getTime();
				Long blackTime=reqUrlList.get(url);
				if (blackTime!=null&&nowTime-blackTime>1000*60*60*24) {//24小时后解除
					reqUrlList.remove(url);
					return false;
				}
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 删除
	 * @param url
	 * @param ip
	 * @return
	 */
	public static boolean delBlackListInfo(String url,String ip){
		if (ip!=null&&checkIp(ip)) {
			ipBlackList.remove(ip);
		}
		if (url!=null&&checkUrl(url)) {
			reqUrlList.remove(url);
		}
		return true;
	}
	
	public static void main(String[] args) {
		/*int time=(int)((new Date().getTime()-DateUtil.getCalendarByAdd(new Date(), Calendar.SECOND, -2000).getTime())/1000);
		System.out.println(time);*/
		int index=1000;
		int y=800;
		System.out.println((y/(float)index)>=0.8F);
	}
}
